"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 数据库系统
Case Name   : 主节点数据磁盘不足，查看集群状态，在主节点进行数据插入，在主备上进行查询
Create At   : 2020/07/25
@zou_jialiang0505328126
Description :
    1.主节点注入磁盘不足故障
    2.查看集群状态
    3.主节点上创建表并插入数据
    4.备节点执行查询指令，查看备节点是否正常
    5.主节点进行数据恢复
    6.清理故障
    7.主节点数据恢复
Expect      :
    1.主节点注入磁盘不足故障成功
    2.查看集群状态（主机查询失败，备机查询成功）
    3.主节点上创建表并插入数据失败
    4.备节点执行查询指令，查看备节点正常
    5.主节点进行数据失败
    6.清理故障成功
    7.主节点数据恢复成功
History     :
    modified：2021/03/01  modified by @peilinqian，修改故障注入方式（线程注入）；优化整个用例
"""

import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import *
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class Disk_full(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info("----this is setup----")
        self.pri_dbuser = Node(node='PrimaryDbUser')
        self.pri_root = Node(node='PrimaryRoot')
        self.sta1_dbuser = Node(node='Standby1DbUser')
        self.sta1_root = Node(node='Standby1Root')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.sta_1_sh = CommonSH('Standby1DbUser')
        self.com = Common()
        self.constant = Constant()
        self.DB_DISK_NAME = ''
        self.dump_file_name = 'test_pid.tar'
        self.file_name = os.path.join(macro.DB_INSTANCE_PATH,
                                      self.dump_file_name)
        self.log.info('----dump file----')
        dump_result = self.pri_sh.dumpFile(self.file_name,
                                           get_detail=False)
        self.log.info(dump_result)
        self.assertTrue(dump_result)

        self.log.info("-----创建restore数据库----")
        self.new_db_name = 'restore_dbsys_133'
        self.create_db_cmd = f'drop database if exists {self.new_db_name};' \
            f'create database {self.new_db_name};'
        self.drop_db_cmd = f'drop database {self.new_db_name};'
        create_db_result = self.pri_sh.executDbSql(self.create_db_cmd)
        self.log.info(create_db_result)
        self.assertIn(self.constant.CREATE_DATABASE_SUCCESS_MSG,
                      create_db_result)

        self.log.info('----Opengauss_Reliability_Dbsys_Case133.py start----')

    def test_disk_full(self):
        self.log.info('----注入磁盘满故障----')
        self.log.info("----获取主机磁盘信息 ----")
        df_cmd = f"df -h {macro.DB_INSTANCE_PATH}"
        self.log.info(df_cmd)
        df_result = self.pri_root.sh(df_cmd).result()
        self.log.info(df_result)
        self.DB_DISK_NAME = df_result.splitlines()[-1].split()[0].strip()

        self.log.info("----注入磁盘满故障 ----")
        inject_cmd = f'rfile_full (diskname) values ({self.DB_DISK_NAME})'
        inject_thread = ComThread(self.com.cfe_inject,
                                  args=(self.pri_root,
                                        inject_cmd,))
        inject_thread.setDaemon(True)
        inject_thread.start()
        time.sleep(10)
        self.log.info("-----获取cfe注入故障结果----")
        inject_thread.join(120)
        inject_result = inject_thread.get_result()
        self.log.info(inject_result)
        success_msg = self.constant.CFE_DISK_FULL_SUCCESS_MSG
        self.assertIn(success_msg, inject_result)

        self.log.info("----主备分别查询数据库状态----")
        self.log.info('主机状态查询')
        pri_status = self.pri_sh.getDbClusterStatus('detail')
        self.log.info(pri_status)
        self.assertIn(self.constant.DISK_FULL_MSG, pri_status)
        self.log.info('备机状态查询')
        sta1_status = self.sta_1_sh.getDbClusterStatus('detail')
        self.assertNotIn(self.constant.DISK_FULL_MSG, sta1_status)

        self.log.info('----主机创建表----')
        create_sql = 'create table test133(id char);'
        create_result = self.pri_sh.executDbSql(create_sql)
        self.log.info(create_result)
        self.assertTrue(self.constant.DISK_FULL_MSG in create_result or
                        self.constant.FAILED_CONNECT_DB in create_result)

        self.log.info('----show table----')
        show_table = self.sta_1_sh.executDbSql(r'\d')
        self.log.info(show_table)

        self.log.info('----进行restore----')
        restore_result = self.pri_sh.restoreFile(self.file_name,
                                                 '',
                                                 True,
                                                 self.new_db_name)
        self.assertIn(self.constant.DISK_FULL_MSG, restore_result)

        self.log.info("----清除磁盘满故障 ----")
        clean_cmd = f'rfile_full where(diskname={self.DB_DISK_NAME})'
        clean_result = self.com.cfe_clean(self.pri_root, clean_cmd)
        self.log.info(clean_result)
        self.assertIn(self.constant.CFE_DISK_CLEAN_SUCCESS_MSG,
                      clean_result)

        self.log.info("----restart opengauss----")
        success_msg = self.constant.RESTART_SUCCESS_MSG
        restart_result = self.pri_sh.executeGsctl('restart',
                                                  success_msg,
                                                  '-M primary')
        self.assertTrue(restart_result)

        self.log.info('----查看主机query，同步是否正常----')
        self.pri_sh.check_location_consistency('primary', 3)

        self.log.info('----查询主备状态----')
        status = self.pri_sh.getDbClusterStatus('status')
        self.assertTrue(status)

        self.log.info('----再次进行restore----')
        restore_result = self.pri_sh.restoreFile(self.file_name,
                                                 '',
                                                 True,
                                                 self.new_db_name)
        self.assertIn(self.constant.RESTORE_SUCCESS_MSG, restore_result)

    def tearDown(self):
        self.log.info('----this is tearDown----')
        df_cmd = f"df -h {macro.DB_INSTANCE_PATH}"
        self.log.info(df_cmd)
        df_result = self.pri_root.sh(df_cmd).result()
        self.log.info(df_result)
        self.USED_PERCENT = df_result.splitlines()[-1].split()[4].strip()
        if self.USED_PERCENT == '100%':
            self.log.info('----异常中断，磁盘故障未恢复处理----')
            clean_disk_cmd = f'rfile_full where(diskname={self.DB_DISK_NAME})'
            clean_disk_result = self.com.cfe_clean(self.pri_root,
                                                   clean_disk_cmd)
            self.log.info(clean_disk_result)

        self.log.info('----删除tar文件----')
        self.pri_dbuser.sh(f'rm -rf {self.file_name}').result()
        self.log.info(self.pri_dbuser.sh(f'ls -l {self.file_name}').result())

        self.log.info("----删除restore库----")
        drop_db_result = self.pri_sh.executDbSql(self.drop_db_cmd)
        self.log.info(drop_db_result)

        self.log.info('----删除表----')
        drop_tb_result = self.pri_sh.executDbSql('drop table test133;')
        self.log.info(drop_tb_result)
